﻿using Basic.FlowModel.AuditLog;
using Basic.FlowModel.AuditLogItem;
using Basic.FlowModel.DB;
using Basic.FlowRemoteModel;
using Basic.FlowRemoteModel.FlowAudit.Model;
using WeDonekRpc.Client;
using WeDonekRpc.Helper;
using WeDonekRpc.Helper.IdGenerator;
using WeDonekRpc.Model;
using WeDonekRpc.SqlSugar;

namespace Basic.FlowDAL.lmpl
{
    internal class FlowAuditLogDAL : BasicDAL<DBFlowAuditLog, long>, IFlowAuditLogDAL
    {
        public FlowAuditLogDAL ( IRepository<DBFlowAuditLog> basicDAL ) : base(basicDAL, "audit.log")
        {
        }
        public Result[] Query<Result> ( AuditLogQuery query, IBasicPage paging, out int count ) where Result : class
        {
            paging.InitOrderBy("Id", true);
            return this._BasicDAL.Query<Result>(query.ToWhere(), paging, out count);
        }
        public long Add ( AuditLogAdd add, out long itemId )
        {
            DBFlowAuditLog log = add.ConvertMap<AuditLogAdd, DBFlowAuditLog>();
            log.Id = IdentityHelper.CreateId();
            log.CreateTime = DateTime.Now;
            log.AuditStatus = FlowAuditStatus.待提交;
            log.Status = FlowAuditLogStatus.待开始;
            log.BeginItemId = IdentityHelper.CreateId();
            DBFlowAuditItemLog item = new DBFlowAuditItemLog
            {
                EmpByDeptId = add.CreateByDeptId,
                BatchNo = log.BeginItemId,
                CompanyId = add.CompanyId,
                EmpId = add.CreateBy,
                NodeType = FlowNodeType.开始节点,
                NodeId = add.BeginNodeId,
                FormId = add.FormId,
                FlowId = add.FlowId,
                RootBatchNo = log.BeginItemId,
                EmpByUnitId = add.CreateByUnitId,
                NodeLvl = 1,
                RootNodeId = add.BeginNodeId,
                LogId = log.Id,
                CreateTime = DateTime.Now,
                Status = FlowAuditItemStatus.审核进行中,
                Id = log.BeginItemId
            };
            DBFlowAuditNodeState[] nodeState = add.NodeId.ConvertAll(a =>
            {
                DBFlowAuditNodeState state = new DBFlowAuditNodeState
                {
                    Id = IdentityHelper.CreateId(),
                    Status = FlowNodeAuditStatus.待开始,
                    NodeId = a.Key,
                    RootNodeId = a.Value,
                    FlowId = add.FlowId,
                    LogId = log.Id
                };
                if ( a.Key == add.BeginNodeId )
                {
                    state.Status = FlowNodeAuditStatus.审核进行中;
                }
                return state;
            });
            ISqlQueue<DBFlowAuditLog> queue = this._BasicDAL.BeginQueue();
            queue.Insert(log);
            queue.InsertBy(item);
            queue.InsertBy(nodeState);
            _ = queue.Submit();
            itemId = item.Id;
            return log.Id;
        }

        public AuditResult SaveAuditResult ( SaveAuditBody body )
        {
            AuditResult result = new AuditResult
            {
                LogId = body.Id,
                ItemId = new List<long>()
            };
            ISqlQueue<DBFlowAuditLog> queue = this._BasicDAL.BeginQueue();
            if ( body.IsChange )
            {
                queue.Update(new DBFlowAuditLog
                {
                    Id = body.Id,
                    Status = body.Status,
                    AuditStatus = body.AuditStatus,
                    ProgressVal = body.ProgressVal,
                    EndTime = body.EndTime,
                    EndEmpId = body.EndEmpId
                }, new string[] { "Status", "AuditStatus", "ProgressVal", "EndEmpId", "EndTime" });
            }
            else if ( body.PChange )
            {
                queue.Update(new DBFlowAuditLog
                {
                    Id = body.Id,
                    ProgressVal = body.ProgressVal
                }, new string[] { "ProgressVal" });
            }
            if ( body.Updates.Count > 0 )
            {
                queue.UpdateBy<DBFlowAuditItemLog>(body.Updates.ConvertAllToArray(a =>
                {
                    result.ItemId.Add(a.Id);
                    return new DBFlowAuditItemLog
                    {
                        Id = a.Id,
                        Status = a.Status,
                        AuditState = a.AuditState,
                        SubFlowState = a.SubFlowState,
                        BackNodeId = a.BackNodeId,
                        EndTime = a.EndTime,
                        AuditOpinion = a.AuditOpinion,
                        SignFileId = a.SignFileId,
                        OptItemId = a.OptItemId
                    };
                }), new string[] { "AuditState", "Status", "SubFlowState", "BackNodeId", "EndTime", "AuditOpinion", "SignFileId", "OptItemId" });
            }
            if ( body.Adds.Count > 0 )
            {
                long batchNo = IdentityHelper.CreateId();
                List<DBFlowAuditItemLog> adds = new List<DBFlowAuditItemLog>(body.Adds.Count);
                DateTime now = DateTime.Now;
                List<DBFlowAuditCopyLog> msgs = new List<DBFlowAuditCopyLog>();
                body.Adds.ForEach(c =>
                {
                    DBFlowAuditItemLog add = c.ConvertMap<AuditLogItemAdd, DBFlowAuditItemLog>();
                    add.CreateTime = now;
                    if ( add.RootBatchNo == 0 )
                    {
                        add.RootBatchNo = batchNo;
                    }
                    if ( c.BatchNo.HasValue == false )
                    {
                        add.BatchNo = batchNo;
                    }
                    add.Id = IdentityHelper.CreateId();
                    adds.Add(add);
                    result.ItemId.Add(add.Id);
                    if ( !c.CopyId.IsNull() )
                    {
                        c.CopyId.ForEach(a =>
                        {
                            msgs.Add(new DBFlowAuditCopyLog
                            {
                                Id = IdentityHelper.CreateId(),
                                LogId = c.LogId,
                                ItemId = add.Id,
                                FromEmpId = add.EmpId,
                                ToEmpId = a,
                                MsgType = FlowMsgType.审核通过,
                                NodeId = c.NodeId,
                                Status = FlowMsgStatus.待发送,
                                AddTime = now,
                            });
                        });
                    }
                });
                queue.InsertBy<DBFlowAuditItemLog>(adds);
                if ( msgs.Count > 0 )
                {
                    queue.InsertBy(msgs);
                }
            }
            if ( body.NodeState.Count > 0 )
            {
                body.NodeState.ForEach(( nodeId, state ) =>
                {
                    queue.UpdateBy<DBFlowAuditNodeState>(a => new DBFlowAuditNodeState
                    {
                        Status = state.Status,
                        OptItemId = state.OptItemId,
                        PrevStatus = state.PrevStatus,
                    }, a => a.LogId == body.Id && a.NodeId == nodeId);
                });
            }
            _ = queue.Submit();
            return result;
        }

        public long Sync ( AuditLogAdd add, long id, out long itemId )
        {
            DBFlowAuditLog log = add.ConvertMap<AuditLogAdd, DBFlowAuditLog>();
            log.Id = IdentityHelper.CreateId();
            log.CreateTime = DateTime.Now;
            log.AuditStatus = FlowAuditStatus.待提交;
            log.BeginItemId = IdentityHelper.CreateId();
            DBFlowAuditItemLog item = new DBFlowAuditItemLog
            {
                CompanyId = add.CompanyId,
                EmpByDeptId = add.CreateByDeptId,
                BatchNo = log.BeginItemId,
                EmpId = add.CreateBy,
                FormId = add.FormId,
                NodeType = FlowNodeType.开始节点,
                NodeId = add.BeginNodeId,
                FlowId = add.FlowId,
                NodeLvl = 1,
                RootBatchNo = log.BeginItemId,
                RootNodeId = add.BeginNodeId,
                EmpByUnitId = add.CreateByUnitId,
                LogId = log.Id,
                CreateTime = DateTime.Now,
                Status = FlowAuditItemStatus.审核进行中,
                Id = log.BeginItemId,
            };
            DBFlowAuditNodeState[] nodeState = add.NodeId.ConvertAll(a =>
            {
                DBFlowAuditNodeState state = new DBFlowAuditNodeState
                {
                    Id = IdentityHelper.CreateId(),
                    Status = FlowNodeAuditStatus.待开始,
                    NodeId = a.Key,
                    RootNodeId = a.Value,
                    FlowId = add.FlowId,
                    LogId = log.Id
                };
                if ( a.Key == add.BeginNodeId )
                {
                    state.Status = FlowNodeAuditStatus.审核进行中;
                }
                return state;
            });
            ISqlQueue<DBFlowAuditLog> queue = this._BasicDAL.BeginQueue();
            queue.Insert(log);
            queue.InsertBy(item);
            queue.InsertBy(nodeState);
            queue.Update(new DBFlowAuditLog
            {
                AuditStatus = FlowAuditStatus.已作废,
                Status = FlowAuditLogStatus.已结束,
                EndTime = DateTime.Now
            }, new string[] { "Status", "AuditStatus", "EndTime" }, a => a.Id == id && a.Status == FlowAuditLogStatus.待开始);
            _ = queue.Submit();
            itemId = log.BeginItemId;
            return log.Id;
        }

        public void Close ( DBFlowAuditLog log, long empId )
        {
            ISqlQueue<DBFlowAuditLog> queue = this._BasicDAL.BeginQueue();
            queue.Update(new DBFlowAuditLog
            {
                Id = log.Id,
                Status = FlowAuditLogStatus.已结束,
                AuditStatus = FlowAuditStatus.已关闭,
                EndTime = DateTime.Now,
                EndEmpId = empId
            }, new string[] { "Status", "AuditStatus", "EndEmpId", "EndTime" });
            queue.UpdateByOneColumn<DBFlowAuditItemLog>(a => a.Status == FlowAuditItemStatus.已作废, a => a.LogId == log.Id && a.Status == FlowAuditItemStatus.审核进行中);
            queue.UpdateByOneColumn<DBFlowAuditNodeState>(a => a.Status == FlowNodeAuditStatus.已取消, a => a.LogId == log.Id && a.Status == FlowNodeAuditStatus.审核进行中);
            _ = queue.Submit();
        }
    }
}
